
package com.filetransfer.client.singlesend;


import java.io.File;
import java.sql.Timestamp;
import com.filetransfer.client.FileTransferInterface;
import com.filetransfer.client.SendFileHandle;
import com.filetransfer.client.state.TransferControl;
import com.filetransfer.config.FileClientConfig;
import com.filetransfer.config.ReceiveFileMessageConfig;
import com.filetransfer.eis.FileInfo;
import com.filetransfer.global.ThreadPoolFactory;
import com.filetransfer.server.message.ReceiveFileMessagePulse;
import com.filetransfer.server.message.callback.EdenReceiveFileMessageCallBack;
import com.filetransfer.transport.command.FileInfoMessage;
import com.filetransfer.transport.util.FileInfoMessageUtil;
import com.filetransfer.util.FileIdUtil;
import com.filetransfer.util.FileInfoUtil;
import com.filetransfer.util.LogUtil;
import com.filetransfer.util.MD5Util;



/**
 * 功能说明:  单文件传输<br>
 * 开发人员: hanxuetong <br>
 * 开发时间: 2014-7-25 <br>
 * 修改日期 修改人员 修改说明  <br>u
 * ======== ====== ============================================ <br>
 * 
 */

public class SingleSendClient implements FileTransferInterface {


	
	private FileClientConfig clientConfig;
	private int failResendCount=3; //错误重传
	private SendCallBack sendCallBack;
	private TransferControl transferControl;
	
	public SingleSendClient(FileClientConfig clientConfig)
	{
		if(clientConfig==null)
		{
			throw new RuntimeException("clientConfig不能为空！");
		}
		this.clientConfig=clientConfig;
		failResendCount=clientConfig.getFailResendCount();
	}
	
	public SingleSendClient(FileClientConfig clientConfig,SendCallBack sendCallBack)
	{
		if(clientConfig==null)
		{
			throw new RuntimeException("clientConfig不能为空！");
		}
		this.clientConfig=clientConfig;
		failResendCount=clientConfig.getFailResendCount();
		this.sendCallBack=sendCallBack;
	}
	
	/**
	 * 发送文件: sendToIp,sendToPort使用 clientConfig
	 * @param wantFilePath
	 * @param fileInfo
	 */
	public void sendFile(String wantFilePath,FileInfo fileInfo)
	{
			
		 sendFile(wantFilePath, fileInfo, clientConfig.getSendToIp(), clientConfig.getSendToPort(),clientConfig.getTargetIp(),clientConfig.getTargetPort());
	}
	
	
	public void sendFile(String wantFilePath,FileInfo fileInfo,String sendToIp,Integer sendToPort)
	{
		
		/*//String wantFilePath=SendFileUtil.getDefaultFileName(fileInfo.getFilePath());
		//填补fileInfo信息，如果以下属性不存在，会根据FilePath来计算，
		FileInfoUtil.putFileInfoPro(fileInfo, clientConfig.isIsMd5Check());	
		FileInfoMessage fileInfoMessage=transportFileInfo(fileInfo,sendToIp,sendToPort,clientConfig.isTransit());
		fileInfoMessage.setWantRelativePath(wantFilePath);
		sendFile(fileInfoMessage);  */
		sendFile(wantFilePath,fileInfo,sendToIp,sendToPort,null,null);
	}
	
	
	public void sendFile(String wantFilePath,FileInfo fileInfo,String sendToIp,Integer sendToPort,String targetIp,Integer targetPort)
	{
		FileInfoUtil.putFileInfoPro(fileInfo, clientConfig.isIsMd5Check());	
		FileInfoMessage fileInfoMessage=transportFileInfo(fileInfo,sendToIp,sendToPort,clientConfig.isTransit());
		fileInfoMessage.setTargetIp(targetIp);
		fileInfoMessage.setTargetPort(targetPort);
		fileInfoMessage.setWantRelativePath(wantFilePath);
		sendFile(fileInfoMessage);  		
	}
	
	
	/**
	 * 发送文件
	 * @param fileInfoMessage
	 */
	public void sendFile(FileInfoMessage fileInfoMessage)
	{
		//如果fileInfoMessage某些值不存在，填补clientConfig某些信息到 fileInfoMessage
		FileInfoMessageUtil.putConfigToFileInfoMessage(clientConfig, fileInfoMessage);
		fileInfoMessage.setStartSendLongTime(System.currentTimeMillis()); //开始发送时时间
		if(transferControl!=null&&transferControl.getClientFilePlugin()!=null) //拦截
		{
			
			transferControl.getClientFilePlugin().sendFileBefore(fileInfoMessage);
			
		}
		
	   //
		if(clientConfig.isThreadPoolSend())  //用线程池发送文件
		{
			ThreadPoolFactory.getExecutorService().execute(new SendFileHandle(clientConfig,fileInfoMessage,this));  
			
		}else{
			new SendFileHandle(clientConfig,fileInfoMessage,this).run();
		}
	
	}


	private FileInfoMessage transportFileInfo(FileInfo fileInfo,String sendToIp,
			Integer sendToPort, boolean isTransit)
	{
		FileInfoMessage fileInfoMessage=FileInfoMessageUtil.fileInfoToFileInfoMessage(fileInfo,isTransit);
		fileInfoMessage.setSendToIp(sendToIp);
		fileInfoMessage.setSendToPort(sendToPort);
		fileInfoMessage.setTransit(isTransit);
		return fileInfoMessage;
	}

	/**
	 * 传输成功回调
	 */
	public void sucessTransferCallBack(FileInfoMessage fileInfoMessage) {

		if(sendCallBack!=null)
		{
			sendCallBack.sucessSendCallBack(fileInfoMessage);
		}
	}

	/**
	 * 一次传输失败回调，如果failResendCount大于0，错误重传
	 */
	public void failTransferCallBack(FileInfoMessage fileInfoMessage) {
		
		failResendCount--;
		if(failResendCount>=0)
		{
			LogUtil.echo(fileInfoMessage.getAbsolutePath()+" "+fileInfoMessage.getWantRelativePath()+"进行错误重传!", this);
			this.sendFile(fileInfoMessage);
		}else{
			//经过错误重传后，最终传送失败
			finalFailTransferCallBack(fileInfoMessage);
		}
		
	}
	/**
	 * 经过错误重传后，最终传送失败
	 * @param fileInfoMessage
	 */
	public void finalFailTransferCallBack(FileInfoMessage fileInfoMessage)
	{
		if(sendCallBack!=null)
		{
			sendCallBack.failSendCallBack(fileInfoMessage);
		}
		
	}

	
	public TransferControl getTransferControl() {
		return transferControl;
	}

	public void setTransferControl(TransferControl transferControl) {
		this.transferControl = transferControl;
	}
	
	public static void main(String[] args) {
		
		
/*		
		
		List<FileInfo> sendfileList=new ArrayList<FileInfo>();
		
	
		 int num=0;
		 LinkedList<File> list = new LinkedList<File>();
		    File dir = new File("E:\\upload");
		    File files[] = dir.listFiles();
		    for (int i = 0; i < files.length; i++) {
		        if (files[i].isDirectory())
		            list.add(files[i]);
		        else{
		           // System.out.println(file[i].getAbsolutePath());
		        	getFileInfoAndPutList(sendfileList,files[i].getAbsolutePath());
		            num++;
		        }
		    }
		    File tmp;
		    while (!list.isEmpty()) {
		        tmp = (File)list.removeFirst();//首个目录
		        if (tmp.isDirectory()) {
		            files = tmp.listFiles(); 
		            if (files == null)
		                continue;
		            for (int i = 0; i < files.length; i++) {
		                if (files[i].isDirectory())
		                    list.add(files[i]);//目录则加入目录列表，关键
		                else{
		                	getFileInfoAndPutList(sendfileList,files[i].getAbsolutePath());
		                    num++;
		                }
		            }
		        } else {
		        	getFileInfoAndPutList(sendfileList,tmp.getAbsolutePath());
		            num++;
		        }
		    }
		    
		
		
		for(int i=0;i<sendfileList.size();i++)
		{
		FileInfo fileInfo=sendfileList.get(i);
			SingleTransferClient client=new SingleTransferClient();
			Runnable run=new SendFileHandle(fileInfo,GlobalProperties.SEND_FILE_PATH,client,"localhost",112);
			Thread thread=new Thread(run);
			thread.start();
		}*/
	/*	String absolutePath="E:\\upload\\phpstudy2010.zip";
		FileInfo fileInfo=new FileInfo();
    	File file=new File(absolutePath);
    	fileInfo.setFilePath(absolutePath);
    	fileInfo.setFileName(file.getName());
    	fileInfo.setFileSize(file.length()+"");
    	
    	fileInfo.setId(FileIdUtil.createFileId(fileInfo.getFilePath(), fileInfo.getFileSize()));   	

    	fileInfo.setState(0);
    	Timestamp createDttm = new Timestamp(System.currentTimeMillis()); 
    	fileInfo.setCreateDttm(createDttm);
    	fileInfo.setStateInfo(FileInfo.getStateInfoByState(fileInfo.getState()));

			String md5=MD5Util.getMD5(file);
			fileInfo.setMd5(md5);
			
			for(int i=0;i<1;i++)
			{
		
				SingleTransferClient client=new SingleTransferClient();
				String wantFilePath=SendFileUtil.getDefaultFileName(fileInfo.getFilePath());
				Runnable run=new SendFileHandle(fileInfo,wantFilePath,client,"localhost",112,false);
				Thread thread=new Thread(run);
				thread.start();
			}	*/
			
		String absolutePath="E:\\upload\\Ch03、Java OOP - 类和对象上机作业.pdf";
		FileInfo fileInfo=new FileInfo();
    	fileInfo.setFilePath(absolutePath);
    	FileInfoUtil.putFileInfoPro(fileInfo, true);
    	//单文件不中转
    	//FileClientConfig clientConfig=new FileClientConfig(false,true, false,"localhost",111);
    	//单文件中转
    	FileClientConfig clientConfig=new FileClientConfig(false,true, true,"localhost",111,"localhost",112,201);
    	
    	EdenReceiveFileMessageCallBack edenReceiveFileMessageCallBack=new EdenReceiveFileMessageCallBack(null);
		ReceiveFileMessageConfig receiveFileMessageConfig=new ReceiveFileMessageConfig(clientConfig.getReceiveMsgPort(), edenReceiveFileMessageCallBack);
		ReceiveFileMessagePulse receiveFileMessagePulse=new ReceiveFileMessagePulse(receiveFileMessageConfig);
		receiveFileMessagePulse.start();
    	
    	SingleSendClient SingleTransferClient=new SingleSendClient(clientConfig);
    	SingleTransferClient.sendFile("dsds.pdf", fileInfo);
    	for(int i=0;i<1;i++)
		{
    		SingleTransferClient=new SingleSendClient(clientConfig);
    		SingleTransferClient.sendFile("dsdsd"+i+".pdf", fileInfo);
    
		}
	}


	
}
